package org.jsoup.parser;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

import org.jsoup.helper.Validate;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.parser.HtmlTreeBuilder;
import org.jsoup.parser.ParseErrorList;
import org.jsoup.parser.Parser;

public class ParallelPartialParser implements Callable<Node> {
	private String name;
	public String partialHtml;
	private Element root;
	public CountDownLatch cdl;
	public boolean isParsing;
	public boolean terminate;
	
	public ParallelPartialParser(String name, File partialHtml, CountDownLatch cdl) throws Exception {
		this.name = name;
		// file to string
		long readStart = System.currentTimeMillis();
		this.partialHtml = new String(Files.readAllBytes(Paths.get(partialHtml.toString())));
		long readEnd = System.currentTimeMillis();
		System.out.println(name + " string converting time is " + (readEnd - readStart) + "ms");
		this.cdl = cdl;
	}
	
	public ParallelPartialParser(String name, String partialHtml, CountDownLatch cdl) throws Exception {
		this.name = name;
		this.partialHtml = partialHtml;
		this.cdl = cdl;
		this.isParsing = false;
		this.terminate = false;
	}
	
	public Node call() {
		try {
//			long start = System.currentTimeMillis();
			
		   	// these two lines are quoted from Document.createShell.
	    	Validate.notNull("");
	        Document doc = new Document("");
	        
	    	// Document.createShell appends three tags(html, head, body) automatically
	        // But we start with empty root
	        root = doc.empty();

	        // for pre-initialising
	        HtmlTreeBuilder treeBuilder = new HtmlTreeBuilder();
	        treeBuilder.initialise(partialHtml, root, "", ParseErrorList.noTracking());
	        
	        // 메인스레드에서 얘의 partialHtml을 진짜 string으로 넘겨줄 때까지 재워둬야 함. 나중에 수정할 것 ㅇㅇ
	        while (isParsing == false) {
	        	try {
	        		if (terminate == true) return null;
	        		
	        		Thread.sleep(10);
	        	} catch (InterruptedException e) {
	        		
	        	}
	        }
	        
	        List<Node> nodeList = treeBuilder.parseFragment_(partialHtml, root, "", ParseErrorList.noTracking());
	        
	        // from 'Parser.parseBodyFragment'
//	        List<Node> nodeList = Parser.parseFragment(partialHtml, root, "");	        
	        Node[] nodes = nodeList.toArray(new Node[nodeList.size()]);
	        for (Node node : nodes) {
	            root.appendChild(node);
	        }
	        
//			long end = System.currentTimeMillis();
			//System.out.println(name + " has terminated and passed time is " + (end - start) + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			cdl.countDown();
		}
		
//		long nanos = ManagementFactory.getThreadMXBean().getThreadCpuTime(Thread.currentThread().getId());
//		System.out.println("thread CPU Time: " + nanos);
//		System.out.println(name + " end");
		
		// 초기화 코드
		isParsing = false;
		
		return root;
	}

}
